import random
import os
from pathlib import Path
from typing import List
from typing import Union
import shutil

"""
将二级子目录(相对于顶层目录)
随机且批量
移动到一级子目录(相对于顶层目录)
主要参数: 顶层目录
"""

KEY_PARENT_DIRECORY = "PARENT_DIRECORY"
KEY_SUB_DIRECTORIES = "SUB_DIRECTORIES"

JSON_FOLDER = "JSON_FOLDER"

LOG_DIRECTOR = f"LOG_DIRECTOR{os.sep}"
ERROR_DETAILS_LOG = f"{LOG_DIRECTOR}ERROR_DETAILS.LOG"
MV_HISTORY_RECORD = f"{LOG_DIRECTOR}MV_HISTORY_RECORD.LOG"
SUCESS_MOVE_LOG = f"{LOG_DIRECTOR}SUCESS_MOVE.LOG"


def initialization_files():
    files_lst = [ERROR_DETAILS_LOG, MV_HISTORY_RECORD, SUCESS_MOVE_LOG]
    for element in files_lst:
        write_file("", element)


def move_file(original_path, destination_path):
    """
    将文件从原路径移动到目标路径
    参数:
        original_path (str): 源路径
        destination_path (str): 目标路径
    返回:
        bool: 移动成功返回True,失败返回False
    """
    try:
        # 获取目标路径的父目录
        dest_parent_dir = os.path.dirname(destination_path)

        # 如果目标父目录不存在,则创建它
        if dest_parent_dir and not os.path.exists(dest_parent_dir):
            os.makedirs(dest_parent_dir, exist_ok=True)
            print(f"已自动创建目标目录: {dest_parent_dir}")

        # 执行移动操作
        shutil.move(original_path, destination_path)

        victory_notice = f"移动成功:'{original_path}'->'{destination_path}'\n"
        write_file(victory_notice, SUCESS_MOVE_LOG, "a")
        print(victory_notice)
        return True
    except FileNotFoundError as e:
        error_details = f"FileNotFound:{original_path}:错误:\n{e}\n"
        write_file(error_details, ERROR_DETAILS_LOG, "a")
        print(error_details)
        return False
    except PermissionError as e:
        error_details = f"权限错误: {e}\n"
        write_file(error_details, ERROR_DETAILS_LOG, "a")
        print(error_details)
        return False
    except shutil.Error as e:
        # shutil.Error 是一个特定的异常,例如,将目录移动到其自身内部
        error_details = f"移动错误: {e}\n"
        write_file(error_details, ERROR_DETAILS_LOG, "a")
        print(error_details)
        return False
    except OSError as e:
        error_details = f"系统错误: {e}\n"
        write_file(error_details, ERROR_DETAILS_LOG, "a")
        print(error_details)
        return False
    except Exception as e:
        error_details = f"未知错误: {e}\n"
        write_file(error_details, ERROR_DETAILS_LOG, "a")
        print(error_details)
        return False


def write_file(
    content: Union[str, bytes],
    filepath: str,
    write_mode: str = "w",
    encoding: str = "utf-8",
) -> bool:
    """
    将content以覆盖形式写入文件filepath
    参数:
        content (str|bytes): 要写入的内容,可以是字符串或字节
        filepath (str): 文件路径
        encoding (str): 编码格式,默认为'utf-8'
    返回:
        bool: 写入成功返回True,失败返回False
    异常:
        FileNotFoundError: 父目录不存在
        PermissionError: 没有写入权限
        UnicodeEncodeError: 编码错误
        OSError: 其他系统错误
    """
    try:
        # 检查父目录是否存在,如果不存在则创建
        parent_dir = os.path.dirname(filepath)
        if parent_dir and not os.path.exists(parent_dir):
            os.makedirs(parent_dir, exist_ok=True)

        # 写入文本内容
        with open(filepath, write_mode, encoding=encoding) as file:
            file.write(str(content))
        return True
    except FileNotFoundError as e:
        print(f"错误：文件路径不存在 - {e}")
        return False
    except PermissionError as e:
        print(f"错误：没有写入权限 - {e}")
        return False
    except UnicodeEncodeError as e:
        print(f"错误：编码失败 - {e}")
        return False
    except OSError as e:
        print(f"错误：系统错误 - {e}")
        return False
    except Exception as e:
        print(f"错误：未知错误 - {e}")
        return False


def obtain_subdirectories(directory_path: str) -> List[str]:
    """
    获取指定目录下所有一级子目录的绝对路径
    参数:
        directory_path (str): 目录路径
    返回:
        List[str]: 包含所有一级子目录绝对路径的列表
    异常:
        FileNotFoundError: 当指定目录不存在时抛出
        NotADirectoryError: 当指定路径不是目录时抛出
    """
    # 方法1: 使用 pathlib (推荐)
    try:
        dir_path = Path(directory_path)

        # 检查路径是否存在
        if not dir_path.exists():
            raise FileNotFoundError(f"目录不存在: {directory_path}")

        # 检查是否是目录
        if not dir_path.is_dir():
            raise NotADirectoryError(f"路径不是目录: {directory_path}")

        # 获取所有一级子目录的绝对路径
        subdirectories = []
        for item in dir_path.iterdir():
            if item.is_dir():
                subdirectories.append(str(item.absolute()))
        return subdirectories
    except Exception as e:
        raise e


def generate_random_integer(min_val, max_val):
    """
    生成指定范围内的随机整数
    参数:
        min_val (int): 最小值（包含）
        max_val (int): 最大值（包含）
    返回:
        list: 包含quantity个随机整数的列表
    """
    try:
        # 生成随机整数
        random_number = random.randint(min_val, max_val)
        return random_number
    except Exception as e:
        print(e)


def generate_record_json(parent_folder, folder_obj):
    os.makedirs(JSON_FOLDER, exist_ok=True)

    json_file_name = parent_folder.replace(os.sep, "-")
    json_file_name = json_file_name.replace(":", "-")
    json_file_path = f"{JSON_FOLDER}{os.sep}{json_file_name}.json"
    write_file(folder_obj, json_file_path)


def obtain_parent_dir_obj(parent_folder: str):
    sub_directories = obtain_subdirectories(parent_folder)
    parent_folder_obj = {}
    parent_folder_obj[KEY_PARENT_DIRECORY] = parent_folder
    parent_folder_obj[KEY_SUB_DIRECTORIES] = sub_directories

    generate_record_json(parent_folder, parent_folder_obj)
    return parent_folder_obj


def execute_move_dir(top_parent_dir_obj, first_tier_dir_obj):
    top_tier_subdirs = top_parent_dir_obj[KEY_SUB_DIRECTORIES]
    # 使用 random.shuffle 打乱列表
    random.shuffle(top_tier_subdirs)
    top_tier_subdirs_count = len(top_tier_subdirs)

    first_tier_subdirs = first_tier_dir_obj[KEY_SUB_DIRECTORIES]
    # 使用 random.shuffle 打乱列表
    random.shuffle(first_tier_subdirs)
    first_tier_subdirs_count = len(first_tier_subdirs)

    for _ in range(first_tier_subdirs_count):
        top_index = generate_random_integer(0, top_tier_subdirs_count - 1)
        subdirs_index = generate_random_integer(0, first_tier_subdirs_count - 1)

        origin_sub_dir = first_tier_subdirs[subdirs_index]
        destionation_parent_dir = top_tier_subdirs[top_index]

        if destionation_parent_dir not in origin_sub_dir:
            command_line = f'mv "{origin_sub_dir}" "{destionation_parent_dir}";\n'
            write_file(command_line, MV_HISTORY_RECORD, "a")
            # print(command_line)
            move_file(origin_sub_dir, destionation_parent_dir)


def main():
    initialization_files()

    top_parent_folder = r"F:\0ab2"
    top_parent_dir_obj = obtain_parent_dir_obj(top_parent_folder)

    top_parent_subdir_lst = top_parent_dir_obj[KEY_SUB_DIRECTORIES]
    # 使用 random.shuffle 打乱列表
    random.shuffle(top_parent_subdir_lst)

    for item in top_parent_subdir_lst:
        first_tier_dir_obj = obtain_parent_dir_obj(item)
        execute_move_dir(top_parent_dir_obj, first_tier_dir_obj)


main()
